﻿//
// OperatorViewModel.cs
//
// Authors:
//    Anders Gade Nørskov <09549@iha.dk
//    Lars Rønde Hansen <09548@iha.dk>
//    Claus Jørgensen <10229@iha.dk>
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Input;
using System.Diagnostics;
using System.Windows.Threading;
using System.Windows;

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;

namespace RSD.ViewModel
{
    using Data;
    using Scripting;
    using Messages;

    public class OperatorViewModel : ViewModelBase
    {
        private readonly IScriptRepository scriptRepository;
        private readonly IScorBotScript scorbotScript;
        private readonly ItemClassificationRepository itemClassificationRepository;
        private readonly RelayCommand startProgramCommand;

        private string description;
        private Script selectedScript;

        public OperatorViewModel(IScriptRepository scriptRepository, 
            IScorBotScript scorbotScript,
            ItemClassificationRepository itemClassificationRepository)
        {
            this.scriptRepository = scriptRepository;
            this.scorbotScript = scorbotScript;
            this.itemClassificationRepository = itemClassificationRepository;

            this.startProgramCommand = new RelayCommand(StartProgramExecute);

            this.MeasuredItems = new ObservableCollection<MeasuredItemSummary>();
            foreach (var item in itemClassificationRepository.FindAll())
            {
                MeasuredItems.Add(new MeasuredItemSummary()
                {
                    ItemClassification = item,
                    Count = 0
                });
            }

            this.Scripts = new ObservableCollection<Script>(scriptRepository.FindAll());
            this.RobotMovements = new ObservableCollection<MovementMessage>();
            this.ItemSummary = new ObservableCollection<MeasuredItem>();

            this.scorbotScript.ActionExecuted += ScorBotScript_ActionExecuted;
            this.scorbotScript.ItemAdded += ScorBotScript_ItemAdded;
        }

        public string Description
        {
            get
            {
                return description;
            }
            set
            {
                description = value;
                RaisePropertyChanged("Description");
            }
        }

        public Script SelectedScript
        {
            get
            {
                return selectedScript;
            }
            set
            {
                selectedScript = value;
                RaisePropertyChanged("SelectedScript");
            }
        }

        public ObservableCollection<Script> Scripts
        {
            get;
            set;
        }

        public struct MovementMessage
        {
            public DateTime MessageTime
            {
                get;
                set;
            }
            
            public string Message
            {
                get;
                set;
            }
        }

        public ObservableCollection<MovementMessage> RobotMovements
        {
            get;
            set;
        }

        public ObservableCollection<MeasuredItem> ItemSummary
        {
            get;
            set;
        }

        public class MeasuredItemSummary : ViewModelBase
        {
            private ItemClassification itemClassification;
            private int count;

            public ItemClassification ItemClassification 
            {
                get
                {
                    return itemClassification;
                }
                set
                {
                    itemClassification = value;
                    RaisePropertyChanged("ItemClassification");
                }
            }

            public int Count
            {
                get
                {
                    return count;
                }
                set
                {
                    count = value;
                    RaisePropertyChanged("Count");
                }
            }
        }

        public ObservableCollection<MeasuredItemSummary> MeasuredItems
        {
            get;
            set;
        }

        public ICommand StartProgramCommand
        {
            get
            {
                return startProgramCommand;
            }
        }

        private void ScorBotScript_ActionExecuted(object sender, ActionExecutedEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(new Action(() => 
            {
                RobotMovements.Add(new MovementMessage() 
                {
                    Message = e.Message,
                    MessageTime = DateTime.Now                      
                });
            }));
        }

        private void ScorBotScript_ItemAdded(object sender, ItemAddedEventArgs e)
        {
            Application.Current.Dispatcher.Invoke(new Action(() => 
            {
                var item = MeasuredItems.FirstOrDefault(
                    x => x.ItemClassification == e.ItemAdded.ItemClassification);

                if (item != null)
                {
                    item.Count += 1;
                }                

                RaisePropertyChanged("MeasuredItems");
            }));
        }

        private void StartProgramExecute()
        {
            try
            {
                scorbotScript.ActionExecuted += (s, e) => Debug.WriteLine(e.Message);
                scorbotScript.ExecuteScriptAsync(SelectedScript.Code, e => 
                {
                    // TODO: Inform Operator of Script Completion, or Error.
                });
            }
            catch (Exception e)
            {
                Messenger.Default.Send(new ExceptionMessage(e));
            }
        }
    }
}
